#include "include/Skill.h"
#include "include/GlobalGameObj.h"
#include "include/Utils.h"

#include <stdlib.h>
#include <boost/lexical_cast.hpp>
#include <vector>

using namespace boost;

void Skill::GetSkillIno(GlobalGameObj *p_game_obj, int skill_id, SkillInfo *p_info)
{
	string value;

	if(p_game_obj->model_proxy.GetObjectById("tbl_skill", "skill_id", skill_id, value))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "Skill::GetSkillInfo";

		return;
	}

	vector<string> strList;
	Utils::Str2StrList(value, strList, '|');

	int i = 0;

	p_info->skill_id = atoi(strList[i++].c_str());
	p_info->trigger_dander = atoi(strList[i++].c_str());
	p_info->keep_dander = atoi(strList[i++].c_str());
	p_info->effect = strList[i++].c_str();
	p_info->range = strList[i++].c_str();
	p_info->trigger_skill = strList[i++].c_str();
	p_info->intro = strList[i++].c_str();
}

void Skill::GetProfessionalSkillIno(GlobalGameObj *p_game_obj, int skill_id, ProfessionalSkillInfo *p_info)
{
	string value;

	if(p_game_obj->model_proxy.GetObjectById("tbl_professional_skill", "skill_id", skill_id, value))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "Skill::GetProfessionalSkillInfo";

		return;
	}

	vector<string> strList;
	Utils::Str2StrList(value, strList, '|');

	int i = 0;

	p_info->skill_id = atoi(strList[i++].c_str());
	p_info->self_consume_dander = atoi(strList[i++].c_str());
	p_info->enemy_consum_dander = atoi(strList[i++].c_str());
	p_info->effect = strList[i++].c_str();
	p_info->intro = strList[i++].c_str();
}

int Skill::CanPerformSkill(GlobalGameObj *p_game_obj, int skill_id, int dander, vector<string> &buffer_arr)
{
	SkillInfo skill_info;
	GetSkillInfo(p_game_obj, skill_id, &skill_info);
	if(0 != p_game_obj->error_code)
	{
		return 0;
	}

	if(skill_info.trigger_dander > dander)
	{
		return 0;
	}

	ptree condition_tree;
	stringstream stream(skill_info.trigger_condition);
	try
	{
		read_json<ptree>(stream, condition_tree);
	}
	catch(boost::exception &ex)
	{
		p_game_obj->error_code = Common::JsonTreeError;
		p_game_obj->error_str = "parse condition_tree in Skill::CanPerformSkill";

		return 0;
	}

	ptree exclude_tree;

	ptree::const_iterator it = condition_tree.find("exclude");
	if(it != ptree.not_found())
	{
		try
		{
			exclude_tree = condition_tree->get_child("exclude");
			string buffer_str;

			for(ptree::iterator it = exclude_tree.begin(); it != exclude_tree.end(); it++)
			{
				buffer_str = lexical_cast<string>(it->second);
				if(buffer_arr.find(buffer_str) != buffer_arr.end())
				{
					return 0;
				}
			}
		}
		catch(boost::exception &ex)
		{
			p_game_obj->error_code = Common::JsonTreeError;
			p_game_obj->error_str = "parse exclude tree in Skill::CanPerformSkill";

			return 0;
		}
	}

	ptree include_tree;
	it = condition_tree.find("include");
	if(it != ptree.not_found())
	{
		try
		{
			include_tree = condition_tree->get_child("include");
			string buffer_str;

			for(ptree::iterator it = include_tree.begin(); it != include_tree.end(); it++)
			{
				buffer_str = lexical_cast<string>(it->second);
				if(buffer_arr.find(buffer_str) != buffer_arr.end())
				{
					return 1;
				}
			}

			return 0;
		}
		catch(boost::exception &ex)
		{
			p_game_obj->error_code = Common::JsonTreeError;
			p_game_obj->error_str = "parse include tree in Skill::CanPerformSkill";

			return 0;
		}
	}

	return 1;
}